﻿namespace IntegrationTests.Calculator
{
  using System;
  using System.IO;
  using System.Linq;
  using System.Reflection;
  using System.Threading;
  using System.Xml.Linq;
  using Microsoft.VisualStudio.TestTools.UnitTesting;

  /// <summary>
  /// Runs a test of the Calculator BizTalk application where everything is
  /// supposed to work without errors (happy flow).
  /// </summary>
  [TestClass]
  public class HappyFlow
  {
    /// <summary>
    /// The file share where request messages are sent.
    /// </summary>
    private const string SendToFolder = @"\\btap1\TestData\Calculator\In";

    /// <summary>
    /// The file share where response messages are read from.
    /// </summary>
    private const string ReceiveFromFolder = @"\\btap1\TestData\Calculator\Out";
    
    /// <summary>
    /// The entry point for the test.
    /// </summary>
    [TestMethod]
    [Timeout(30000)]
    public void HappyFlowTest()
    {
      string id;
      string responseFilename;
      XDocument request;
      XDocument expectedResponse;
      XDocument actualResponse;
      XNamespace ns1;
      XNamespace ns2;

      // Define the namespaces we need.
      ns1 = "http://contoso.com/biztalkdemo/addrequest/v1";
      ns2 = "http://contoso.com/biztalkdemo/addresponse/v1";

      // Load the docuemnt templates.
      request = XDocument.Load(this.GetResourceStream("AddRequest.xml"));
      expectedResponse = XDocument.Load(this.GetResourceStream("AddResponse.xml"));

      // Create a new unique ID
      id = Guid.NewGuid().ToString();

      // Replace the ID in our messages in order to
      // create a uniqe message for each test run.
      request.Descendants(ns1 + "UnitOfWorkID").First().Value = id;
      expectedResponse.Descendants(ns2 + "UnitOfWorkID").First().Value = id;

      // Send the request message to BizTalk, using the ID as the file name.
      request.Save(Path.Combine(SendToFolder, id + ".xml"));

      // The BizTalk application outputs the original filename,
      // so we know what to look for.
      responseFilename = Path.Combine(ReceiveFromFolder, id + ".xml");

      // Poll for the file. If BizTalk fails and never outputs the
      // file, the test will stop on time-out.
      while (!File.Exists(responseFilename))
      {
        Thread.Sleep(1000);
      }

      // Load the actual response.
      actualResponse = XDocument.Load(responseFilename);

      // Compare the actual and expected XML documents.
      // Note that the DeepEquals method is sensitive to syntax differences.
      // You may need to adjust the expected message for the comparison to work.
      Assert.IsTrue(XNode.DeepEquals(actualResponse, expectedResponse));
      
      // Cleanup the file
      File.Delete(responseFilename);
    }

    /// <summary>
    /// Get the stream of an embedded file.
    /// </summary>
    /// <param name="name">The file name.</param>
    /// <returns>The stream of the embedded file.</returns>
    private Stream GetResourceStream(string name)
    {
      Assembly asm;
      Stream s;

      asm  = Assembly.GetExecutingAssembly();
      s = asm.GetManifestResourceStream("IntegrationTests.Calculator.TestData.HappyFlow." + name);

      return s;
    }
  }
}
